import { computed, getCurrentInstance, onBeforeMount, ref } from 'vue'
import { browserChannel, getImageUrl } from '@/utils/utils'
import { BrowserChannelType } from '@/hooks/browserHooks'
import { useRunningTasksStore } from '@/stores/taskBar/runningTasks'
import { useSystemSettingStore } from '@/stores/desk/systemSetting'
import { getFileDBStore } from '@/dbStore/fileStore'
import { useRoute } from 'vue-router'
import type { Ref } from 'vue'

export interface IUseSystemSettingHooksReturn {
  dragStart: Ref<boolean>
  dragResizeStart: Ref<boolean>
  systemWindowDom: Ref<HTMLElement | undefined>
  handleMousedownDrag: (ev: MouseEvent) => void
  handleResizeMouseDown: (ev: MouseEvent) => void
}

type CssStyleKey = keyof CSSStyleDeclaration

// 壁纸图片DB名称
export const WALLPAPER = 'WALLPAPER'

// 任务弹窗拖动hooks
export const useSystemWindowHook = (appId: string, taskId: string): IUseSystemSettingHooksReturn => {
  let dragTime = 0
  let topHeight = 0
  const dragStart = ref<boolean>(false)
  const dragResizeStart = ref<boolean>(false)
  const systemWindowDom = ref<HTMLElement>()
  const dragInfo = { x: 0, y: 0 }
  const dragResizeInfo = {
    x: 0,
    y: 0,
    top: 0,
    left: 0,
    width: 0,
    height: 0,
    minWidth: 0,
    minHeight: 0,
    maxWidth: 0,
    maxHeight: 0,
    path: ''
  }
  const emits = getCurrentInstance()?.emit
  const route = useRoute()
  const runningTasksStore = useRunningTasksStore()
  const systemSettingStore = useSystemSettingStore()

  // 拖动窗口
  const handleMousemove = (ev: MouseEvent) => {
    if (!dragStart.value || !systemWindowDom.value) return
    const isOtherWin = route.path === '/default/expand'
    const { mainDesk } = systemSettingStore.$state
    const x = ev.x - dragInfo.x + (isOtherWin ? mainDesk[0] : 0)
    let y = ev.y - dragInfo.y + (isOtherWin ? mainDesk[1] : 0)
    y = y <= 0 ? 0 : y
    // iOS不能超出顶部条,和底部条
    if (systemSettingStore.$state.deskAppRangeType === 'ios') {
      if (!topHeight) {
        const maxTop = document.querySelector('.task-bar.d-f-c.ios')
        topHeight = maxTop?.clientHeight || 0
      }
      y = y <= topHeight ? topHeight : y
    }
    dragTime = 0
    browserChannel.postMessage({ type: BrowserChannelType.taskMove, data: { x, y, appId, taskId } })
    systemWindowDom.value.style.left = `${x}px`
    systemWindowDom.value.style.top = `${y}px`
  }
  const handleMouseup = () => {
    const date = new Date().getTime()
    if (dragStart.value && systemWindowDom.value && date - dragTime > 300) {
      const { left, top } = systemWindowDom.value.getBoundingClientRect()
      emits && emits('dragEnd', { x: left, y: top })
      document.removeEventListener('mousemove', handleMousemove)
      document.removeEventListener('mouseup', handleMouseup)
    }
    browserChannel.postMessage({ type: BrowserChannelType.dragEnd, data: { appId, taskId } })
    runningTasksStore.setTaskPatch(appId, taskId, { isDrag: false })
    dragStart.value = false
  }
  const handleMousedownDrag = (ev: MouseEvent) => {
    if (!systemWindowDom.value) return
    emits && emits('focus')
    dragTime = new Date().getTime()
    const isOtherWin = route.path === '/default/expand' ? 1 : 0
    const { mainDesk } = systemSettingStore.$state
    const { left, top } = systemWindowDom.value.getBoundingClientRect()
    systemSettingStore.setMainDesk(mainDesk[0], mainDesk[1], isOtherWin)
    browserChannel.postMessage({ type: BrowserChannelType.setCurrentWin, data: isOtherWin })
    dragInfo.x = ev.x - left + (isOtherWin ? mainDesk[0] : 0)
    dragInfo.y = ev.y - top + (isOtherWin ? mainDesk[1] : 0)
    dragStart.value = true
    runningTasksStore.setTaskPatch(appId, taskId, { isDrag: true })
    document.addEventListener('mousemove', handleMousemove)
    document.addEventListener('mouseup', handleMouseup)
  }

  // 获取样式
  const getStyleValue = (
    dom: HTMLElement,
    val: CssStyleKey[] | CssStyleKey,
    rep = ''
  ): Partial<CSSStyleDeclaration> => {
    const valList = [val].flat(Infinity) as CssStyleKey[]
    const domStyle = window.getComputedStyle(dom)
    let styleList: Partial<CSSStyleDeclaration> = {}
    valList.forEach((item) => {
      const value = String(domStyle[item]) || ''
      styleList = { ...styleList, [item]: value.replace(rep, '') }
    })
    return styleList
  }

  const resizeToTop = (y: number) => {
    const height = dragResizeInfo.height - y
    if (!systemWindowDom.value || height <= dragResizeInfo.minHeight) return
    systemWindowDom.value.style.top = `${dragResizeInfo.top + y}px`
    systemWindowDom.value.style.height = `${height}px`
  }
  const resizeToRight = (x: number) => {
    if (!systemWindowDom.value) return
    systemWindowDom.value.style.width = `${dragResizeInfo.width + x}px`
  }
  const resizeToBottom = (y: number) => {
    if (!systemWindowDom.value) return
    systemWindowDom.value.style.height = `${dragResizeInfo.height + y}px`
  }
  const resizeToLeft = (x: number) => {
    const width = dragResizeInfo.width - x
    if (!systemWindowDom.value || width <= dragResizeInfo.minWidth) return
    systemWindowDom.value.style.left = `${dragResizeInfo.left + x}px`
    systemWindowDom.value.style.width = `${width}px`
  }

  // 窗口大小拖动
  const handleResizeMousemove = (ev: MouseEvent) => {
    if (!dragResizeStart.value || !systemWindowDom.value) return
    const x = ev.x - dragResizeInfo.x
    const y = ev.y - dragResizeInfo.y
    switch (dragResizeInfo.path) {
      case 'top':
        resizeToTop(y)
        break
      case 'right':
        resizeToRight(x)
        break
      case 'bottom':
        resizeToBottom(y)
        break
      case 'left':
        resizeToLeft(x)
        break
      case 'top-left':
        resizeToLeft(x)
        resizeToTop(y)
        break
      case 'top-right':
        resizeToRight(x)
        resizeToTop(y)
        break
      case 'bottom-left':
        resizeToLeft(x)
        resizeToBottom(y)
        break
      case 'bottom-right':
        resizeToRight(x)
        resizeToBottom(y)
        break
      default:
        break
    }
    browserChannel.postMessage({
      type: BrowserChannelType.resizeMove,
      data: {
        appId,
        taskId,
        left: systemWindowDom.value?.offsetLeft,
        top: systemWindowDom.value?.offsetTop,
        width: systemWindowDom.value?.offsetWidth,
        height: systemWindowDom.value?.offsetHeight
      }
    })
  }
  const handleResizeMouseup = () => {
    if (!systemWindowDom.value) return
    dragResizeStart.value = false
    const { left, top, width, height } = systemWindowDom.value.getBoundingClientRect()
    emits && emits('resizeEnd', { left, top, width, height })
    browserChannel.postMessage({ type: BrowserChannelType.dragEnd, data: { appId, taskId } })
    document.removeEventListener('mousemove', handleResizeMousemove)
    document.removeEventListener('mouseup', handleResizeMouseup)
  }
  const handleResizeMouseDown = (ev: MouseEvent) => {
    if (!systemWindowDom.value) return
    const target = ev.target as HTMLElement
    const rect = systemWindowDom.value?.getBoundingClientRect()
    const style: (keyof CSSStyleDeclaration)[] = ['minWidth', 'minHeight', 'maxWidth', 'maxHeight']
    const { minWidth, minHeight, maxWidth, maxHeight } = getStyleValue(systemWindowDom.value, style, 'px')
    emits && emits('focus')
    dragResizeInfo.x = ev.x
    dragResizeInfo.y = ev.y
    dragResizeInfo.width = rect.width
    dragResizeInfo.height = rect.height
    dragResizeInfo.minWidth = isNaN(Number(minWidth)) ? 0 : Number(minWidth)
    dragResizeInfo.minHeight = isNaN(Number(minHeight)) ? 0 : Number(minHeight)
    dragResizeInfo.maxWidth = isNaN(Number(maxWidth)) ? 0 : Number(maxWidth)
    dragResizeInfo.maxHeight = isNaN(Number(maxHeight)) ? 0 : Number(maxHeight)
    dragResizeInfo.left = rect.left
    dragResizeInfo.top = rect.top
    dragResizeInfo.path = target.dataset.resize || ''
    dragResizeStart.value = true
    document.addEventListener('mousemove', handleResizeMousemove)
    document.addEventListener('mouseup', handleResizeMouseup)
  }

  return {
    dragStart,
    dragResizeStart,
    systemWindowDom,
    handleMousedownDrag,
    handleResizeMouseDown
  }
}

/** 桌面壁纸Hooks */
export const useDeskWallpaperHook = (): { deskWallpaper: Ref<{ background: string }> } => {
  const systemSettingStore = useSystemSettingStore()
  // 桌面壁纸
  const deskWallpaper = computed(() => {
    const wallpaper = systemSettingStore.$state.deskWallpaper
    const wallpaperColor = systemSettingStore.$state.deskWallpaperColor
    const imageType = systemSettingStore.$state.deskBackgroundImageType
    const type = systemSettingStore.$state.deskBackgroundType
    const size = imageType === 'fill' ? '100% 100%' : imageType
    const image = `url(${wallpaper ? wallpaper : getImageUrl('bg2.jpg')}) no-repeat center center / ${size}`

    return {
      background: type === 'image' ? image : type === 'color' ? wallpaperColor : ''
    }
  })

  // 初始化壁纸
  const initWallpaper = async () => {
    try {
      const { base64 } = await getFileDBStore(WALLPAPER)
      if (base64) systemSettingStore.setDeskBackgroundWallpaper(base64)
    } catch {
      const wallpaper = systemSettingStore.$state.deskWallpaper
      if (!wallpaper) systemSettingStore.setDeskBackgroundWallpaper(getImageUrl('bg2.jpg'))
    }
  }

  onBeforeMount(initWallpaper)

  return {
    deskWallpaper
  }
}
